package com.hotel.BL;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.EntityName;
import com.SharedCache;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.Filter;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.FilterPredicate;

import data.CurrencyMaster;
import data.DateTimeFormatMaster;
import data.General;
import data.Hotel;
import data.LanguageMaster;
import data.LoginData;
import data.User;
import data.UserMappingHotel;

public class LoginLogic extends AbstractBL {
	public LoginLogic(HttpServletRequest req,HttpServletResponse resp){
		this.req = req;
		this.resp = resp;
	}
	private final int checkexistuserminute = 30000;
	public HashMap<String,Object> Login(String hotelIdL, String hotelIdS, String email,
			String pass,String sessionid) throws ServletException, IOException {

		LanguageMaster languageMaster = new LanguageMaster();
		DateTimeFormatMaster dateformat = new DateTimeFormatMaster();
		CurrencyMaster currency = new CurrencyMaster();
		LoginData loginData = new LoginData();
		UserLogic userLogic = new UserLogic(req,resp);
		HotelLogic hotelLogic = new HotelLogic();
		GenericLogic generic = new GenericLogic(req,resp);
		UserMappingHotelLogic mappingLogic = new UserMappingHotelLogic(req, resp);
		HashMap<String, Object> hash = new HashMap<String,Object>();
		
		User user = userLogic.GetUser(email, pass);
		if(user == null){
			return ReturnUserDataNull(hash);
		}
		
		Hotel hotel = new Hotel();
		UserMappingHotel mapping = new UserMappingHotel();
		long hotelId = 0;
		if(Long.parseLong(hotelIdS) != 0){
			Hotel h = hotelLogic.GetHotel(Long.parseLong(hotelIdS), hotelIdL);
			if(h != null){
				hotel = h;
				hotelId = hotel.getHotelId();
			}else{
				hotel = hotelLogic.GetHotelByShortCode(Long.parseLong(hotelIdS));
				if(hotel == null){
					return ReturnUserDataNull(hash);
				}else{
					hotelId = Long.parseLong(hotelIdS);					
				}
			}
		}else{
			hotel = hotelLogic.GetHotelByFullCode(hotelIdL);
			if(hotel == null){
				return ReturnUserDataNull(hash);
			}else{
				hotelId = hotel.getHotelId();
			}
		}
		
		mapping = mappingLogic.GetUserMapping(hotelId, String.valueOf(user.getId()));
		if(mapping == null){
			return ReturnUserDataNull(hash);
		}else{
			boolean canShort = mapping.getUserlevel().isShortHotelCode();
			if(!canShort){
				if(!hotelIdS.equals("0") && !Long.toString(hotel.getHotelId()).equals(hotelIdS)){
					return ReturnUserDataNull(hash);
				}
			}
		}
		
		hash.put("workAreaAmount", mapping.getUserlevel().getWorkAreas().size());
		
		long eLastStay = user.getLastStay().getTime();
		long datenow = new GenericLogic(req,resp).ServerDateTime(hotel.getHotelId()).getTime();
		if(datenow - eLastStay  > checkexistuserminute){
			hash.put("intime", false);
		}else{
			hash.put("intime", true);
		}
		String esessionid = sessionid;
		if(user.getSessionid() != null){
			esessionid = user.getSessionid();
		}
		
		if(!esessionid.equals(sessionid)){
			hash.put("checksession", false);
		}else{
			hash.put("checksession", true);
		}
			
				General g = generic.GetGeneral(hotel.getHotelId());
				//String languageCode = g.getDefaultLanguage().getLanguageCode();
				String languageCode = user.getLanguage().getLanguageCode();
				String languageSubCode = user.getLanguage().getLanguageSubCode();
				String languageTitle = user.getLanguage().getTitle();
				String cerrencySymbol = g.getDefaultCurrency().getSymbol();
				String currencyAbreviation = g.getDefaultCurrency().getAbreviation();
				String dateTimeFormat = g.getDateFormat().getDateTimeFormat();
				Short currencyDecimalPlaces = g.getCurrencyDecimalPlaces();
				boolean TimeFormatShow24Hours = g.getTimeFormat();

				languageMaster.setLanguageCode(languageCode);
				languageMaster.setLanguageSubCode(languageSubCode);
				languageMaster.setTitle(languageTitle);

				currency.setSymbol(cerrencySymbol);
				currency.setAbreviation(currencyAbreviation);

				dateformat.setDateTimeFormat(dateTimeFormat);

				loginData.setHotelId(hotel.getHotelId());
				//loginData.setHotelId(hotelId);
				loginData.setDefaultLanguage(languageMaster);
				loginData.setDefaultCurrency(currency);
				loginData.setCurrencyDecimalPlaces(currencyDecimalPlaces);
				loginData.setDateFormat(dateformat);
				loginData.setTimeFormatShow24Hours(TimeFormatShow24Hours);
				loginData.setUser(user);
				
				hash.put("userData", loginData);
		return hash;
	}
	
	public void UpdateLastStay(long hotelId,long userId){
		User user = GetUserWithCache(userId);
		user.setLastStay(new GenericLogic(req,resp).ServerDateTime(hotelId));
		user.setCounterId(user.getCounterId());
		new UserLogic(req,resp).UpdateUser(user);
	}
	
	public User GetUserWithCache(long id){
		if(SharedCache.getSharedCache("LoginLogic.GetUser."+id) != null){
			User rs = (User) SharedCache.getSharedCache("LoginLogic.GetUser."+id);
			User result = new User();
			result.setEntity(rs.getEntity());
			return result;
		}
		else{
			User rs = new UserLogic(req, resp).GetUser(id);
			SharedCache.setSharedCache("LoginLogic.GetUser."+id,rs,86400);
			User result = new User();
			result.setEntity(rs.getEntity());
			return result;
		}
	}
	
	public User GetUserLogin(Entity entity)
	{
		if(entity == null) return null;
		User item = new User();
		item.setEntity(entity);
		return item;
	}
	
	public List<User> GetUserList(List<Entity> entities)
	{
		List<User> list = new ArrayList<User>();
		if(entities!=null)
			for(Entity e : entities)
			{
				User a = new User();
				a.setEntity(e);
				list.add(a);
			}
		return list;
	}
	
	public List<UserMappingHotel> GetUserMappingHotelList(List<Entity> entities)
	{
		List<UserMappingHotel> list = new ArrayList<UserMappingHotel>();
		if(entities!=null)
			for(Entity e : entities)
			{
				UserMappingHotel a = new UserMappingHotel();
				a.setEntity(e);
				list.add(a);
			}
		return list;
	}
	
	public List<UserMappingHotel> GetAllUserMapLimit(long hotelId,long offset,long line)
	{
		Query q = new Query(EntityName.UserMappingHotel);
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		q.setFilter(filterHotel);
		return GetUserMappingHotelList(datastore.prepare(q).asList(FetchOptions.Builder.withLimit((int) line).offset((int)offset)));
	}
	
	public List<UserMappingHotel> GetAllUser(long hotelId)
	{
		Query q = new Query(EntityName.UserMappingHotel);
		Filter filterHotel = new FilterPredicate("hotelId",FilterOperator.EQUAL,hotelId);
		q.setFilter(filterHotel);
		return GetUserMappingHotelList(datastore.prepare(q).asList(
				FetchOptions.Builder.withDefaults()));
	}
	
	public List<User> GetUserLogin(long hotelId)
	{
		Query q = new Query(EntityName.User);
		Filter filterStatus = new FilterPredicate("sessionid",FilterOperator.NOT_EQUAL,null);
		q.setFilter(filterStatus);
		return GetUserList(datastore.prepare(q).asList(
				FetchOptions.Builder.withDefaults()));
	}
	
	public User Logout(long hotelId,long id) throws EntityNotFoundException{
		User a = GetUserWithCache(id);
		a.setSessionid(null);
		a.setCounterId(null);
		Key k = datastore.put(a.getEntity());
		Entity e = datastore.get(k);
		a = new User();
		a.setEntity(e);
		return a;
	}
	
	public User SetCounter(long hotelId,long userId,String counterId) throws EntityNotFoundException{
		User a = GetUserWithCache(userId);
		a.setCounterId(counterId);
		Key k = datastore.put(a.getEntity());
		Entity e = datastore.get(k);
		a = new User();
		a.setEntity(e);
		return a;
	}
	
	public HashMap<String, Object> ReturnUserDataNull(HashMap<String, Object> hash){
		hash.put("userData", null);
		hash.put("intime", false);
		hash.put("checksession", false);
		return hash;
	}
}